package ro.myApp.security.client;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;

import org.ajax4jsf.context.AjaxContext;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
import org.richfaces.component.html.HtmlTree;
import org.richfaces.component.html.HtmlTreeNode;
import org.richfaces.event.DropEvent;
import org.richfaces.event.NodeSelectedEvent;
import org.richfaces.model.TreeNode;
import org.richfaces.model.TreeNodeImpl;

import ro.myApp.client.BaseView;
import ro.myApp.security.dto.RoleCreateMessage;
import ro.myApp.security.dto.RoleSaveMessage;
import ro.myApp.security.dto.RolesFindAllHierarchyMessage;
import ro.myApp.security.dto.UserFindAllFiltered;
import ro.myApp.security.dto.UserFindByUsernameMessage;
import ro.myApp.security.dto.UserSaveMessage;
import ro.myApp.security.entities.Role;
import ro.myApp.security.entities.User;
import ro.myApp.security.util.RoleEnum;

@Name("roles")
@BypassInterceptors
@Scope(ScopeType.PAGE)
public class Roles extends BaseView {

	/**
	 * 
	 */
	private static final long serialVersionUID = -5410712465027004258L;
	
	private TreeNode<Role> treeData;
	
	private TreeNode<Role> selectedNode;
	
	private int numberOfRoots = 0;
	
	private User user;
	
	
	public List<RoleEnum> getAllBasicRoles() {
		return Arrays.asList(RoleEnum.values());
	}
	
	public TreeNode<Role> getTreeData (){
		if (null==treeData){
			treeData=new TreeNodeImpl<Role>();
			List<?> roots = sendMessage(new RolesFindAllHierarchyMessage());
			numberOfRoots=roots.size();
			for (Object root : roots) {
				TreeNode<Role> node = new TreeNodeImpl<Role>();
				node.setData((Role) root);
				treeData.addChild(node.getData().getPath(), node);
				createChildren(node);
			}
			treeData.addChild("plus", new TreeNodeImpl<Role>());
			
		}
		return treeData;
	}
	
	public void createChildren(TreeNode<Role> uiNode) {
		TreeNode<Role> uiChildNode;

		for (Role element : uiNode.getData().getChildren()) {
			uiChildNode = new TreeNodeImpl<Role>();
			uiChildNode.setData(element);
			uiNode.addChild(element.getPath(), uiChildNode);
			if (!element.isLeaf()) {
				createChildren(uiChildNode);
			}
		}		
	}
	
	@SuppressWarnings("unchecked")
	public void selectNode(NodeSelectedEvent event) {
		HtmlTree tree = (HtmlTree) event.getComponent();
		selectedNode = tree.getTreeNode();
	}
	
	public TreeNode<Role> getSelectedNode() {
		return selectedNode;
	}
	
	public String processAcceptedTypes (Role role){
		//the already used types are not accepted by drag&drop
		List<RoleEnum> minus = new LinkedList<RoleEnum>(Arrays.asList(RoleEnum.values()));
		for (Role r : role.getChildren()) {
			if (null!=r.getBaseRole())
				minus.remove(r.getBaseRole());
		}
		StringBuilder sb = new StringBuilder();
		for (RoleEnum roleEnum : minus) {
			sb.append(roleEnum.name());
			sb.append(',');
		}
		return sb.toString();
	}
	
	public void drop (DropEvent dropEvent){
		RoleEnum baseRole = (RoleEnum) dropEvent.getDragValue();
		@SuppressWarnings("unchecked")
		TreeNode<Role> parent = ((HtmlTreeNode) dropEvent.getSource()).getUITree().getTreeNode();
		Role childNode = sendMessage(new RoleCreateMessage(parent.getData(), baseRole));
		TreeNode<Role> uiChildNode = new TreeNodeImpl<Role>();
		uiChildNode.setData(childNode);
		parent.setData(childNode.getParent());
		parent.addChild(childNode.getPath(), uiChildNode);
		selectedNode = parent;
		try{
			UIComponent tree = FacesContext.getCurrentInstance().getViewRoot().findComponent("bodyFrm:rolesTree");
			AjaxContext.getCurrentInstance().addComponentToAjaxRender(tree);
			UIComponent details = FacesContext.getCurrentInstance().getViewRoot().findComponent("bodyFrm:roleDetailsSdiv");
			AjaxContext.getCurrentInstance().addComponentToAjaxRender(details);
		}catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public List<User> getUsersList (){
		if (null!=selectedNode){
			UserFindAllFiltered dto = new UserFindAllFiltered();
			dto.setRole(selectedNode.getData());
			dto.setActive(Boolean.TRUE);
			return sendMessage(dto);
		}
		return null;
	}
	
	public void addRoot (){
		Role root = new Role();
		root.setBaseRole(null);
		root.setLeaf(true);
		root.setRoot(true);
		root.setLevel(1);
		root.setOrder(++numberOfRoots);
		root.setPath(String.valueOf(root.getOrder()));
		
		TreeNode<Role> node = new TreeNodeImpl<Role>();
		node.setData((Role) root);
		treeData.addChild(node.getData().getPath(), node);
		selectedNode=node;
		
		try{
			UIComponent tree = FacesContext.getCurrentInstance().getViewRoot().findComponent("bodyFrm:rolesTree");
			AjaxContext.getCurrentInstance().addComponentToAjaxRender(tree);
			UIComponent details = FacesContext.getCurrentInstance().getViewRoot().findComponent("bodyFrm:roleDetailsSdiv");
			AjaxContext.getCurrentInstance().addComponentToAjaxRender(details);
		}catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void save (){
		@SuppressWarnings("unused")
		Role saved = sendMessage(new RoleSaveMessage(selectedNode.getData()));
	}
	
	public void editUser (String username){
		user = sendMessage(new UserFindByUsernameMessage(username));
	}
	
	public void saveUser (){
		@SuppressWarnings("unused")
		User result = sendMessage(new UserSaveMessage(user));
		user=null;
	}
	
	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}
}
